package com.wstuo.common.config.attachment.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.wstuo.common.config.attachment.dao.IAttachmentDAO;
import com.wstuo.common.config.attachment.dto.AttachmentDTO;
import com.wstuo.common.config.attachment.dto.AttachmentDownloadDTO;
import com.wstuo.common.config.attachment.entity.Attachment;
import com.wstuo.common.dto.PageDTO;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.security.dao.IUserDAO;
import com.wstuo.common.security.entity.User;
import com.wstuo.common.security.utils.AppConfigUtils;
import com.wstuo.common.security.utils.AppContext;
import com.wstuo.common.security.utils.LanguageContent;
import com.wstuo.common.util.StringUtils;
import com.wstuo.common.util.TimeUtils;

/**
 * 附件Service
 * 
 * @author QXY date 2011/2/11
 */
public class AttachmentService implements IAttachmentService {

	@Autowired
	private IAttachmentDAO attachmentDAO;
	private static final Logger LOGGER = Logger.getLogger(AttachmentService.class);
	@Autowired
	private ExtractTextFromAttachment extractTextFromAttachment;
	@Autowired
	private IUserDAO userDAO;
	@Autowired
	private AppContext appctx;
	private static final String ATTACHMENTPATH= AppConfigUtils.getInstance().getAttachmentPath();
	/**
	 * 根据附件编号查询附件信息
	 * 
	 * @param attachmentId
	 * @return Attachment
	 */
	public Attachment findAttachmentById(Long attachmentId) {
		Attachment entity = attachmentDAO.findById(attachmentId);
		return entity;
	}

	/**
	 * 查询附件列表
	 * 
	 * @param qdto
	 * @param start
	 * @param limit
	 * @param sidx
	 * @param sord
	 * @return PageDTO
	 */
	public PageDTO findByPager(AttachmentDTO qdto, int start, int limit, String sidx, String sord) {
		qdto.setCreator(appctx.getCurrentLoginName());// 只查询当前用户的附件
		PageDTO pageDTO = attachmentDAO.findattachmentPager(qdto, start, limit, sidx, sord);
		List<Attachment> list = pageDTO.getData();
		List<AttachmentDTO> dtos = new ArrayList<AttachmentDTO>(list.size());
		for (Attachment att : list) {
			AttachmentDTO dto = new AttachmentDTO();
			AttachmentDTO.entity2dto(att, dto);
			String attachmentDate = TimeUtils.format(att.getCreateTime(),TimeUtils.DATETIME_PATTERN);
			User user = userDAO.findUniqueBy("loginName", att.getCreator());
			if (user != null) {
				dto.setCreator(user.getFullName());
			}
			dto.setCreateTime(attachmentDate);
			dtos.add(dto);
		}
		pageDTO.setData(dtos);
		return pageDTO;
	}

	/**
	 * 保存附件.
	 * 
	 * @param dto
	 *            附件DTO
	 */
	@Transactional
	public void save(AttachmentDTO dto) {

		Attachment entity = new Attachment();
		AttachmentDTO.dto2entity(dto, entity);
		attachmentDAO.save(entity);
		dto.setAid(entity.getAid());
	}

	/**
	 * 删除附件.
	 * 
	 * @param id
	 *            附件编号.
	 */
	@Transactional
	public void delete(Long id) {
		try {
			Attachment entity = attachmentDAO.findById(id);
			attachmentDAO.delete(entity);
		} catch (Exception ex) {
			throw new ApplicationException("ERROR_DATA_CAN_NOT_DELETE", ex);
		}
	}

	/**
	 * 删除附件.
	 * 
	 * @param id
	 *            附件编号.
	 */
	@Transactional
	public boolean deleteReturn(Long id) {
		boolean bool = true;
		try {
			Attachment entity = attachmentDAO.findById(id);
			attachmentDAO.delete(entity);
			bool = false;
		} catch (Exception ex) {
			throw new ApplicationException("ERROR_DATA_CAN_NOT_DELETE", ex);
		}

		return bool;
	}

	/**
	 * 批量删除附件.
	 * 
	 * @param ids
	 *            附件编号数组.
	 */
	@Transactional
	public void delete(Long[] ids) {
		try {
			attachmentDAO.delete(ids);
		} catch (Exception ex) {
			throw new ApplicationException("ERROR_DATA_CAN_NOT_DELETE", ex);
		}
	}

	/**
	 * 保存附件并返回LIST
	 * 
	 * @param attachmentStr
	 * @param type
	 * @return List<Attachment>
	 */
	@SuppressWarnings("unchecked")
    @Transactional
	public List<Attachment> saveAttachment(String attachmentStr, String type) {
		List<Attachment> attrs = new ArrayList<Attachment>();
		if (attachmentStr != null && attachmentStr.indexOf("-s-") != -1) {
			String[] attrArr = attachmentStr.split("-s-");
			for (int i = 0; i < attrArr.length; i++) {
				String url = attrArr[i].replace("\\", "/");
				if (StringUtils.hasText(url)) {
					String[] attrArrs = url.split("==");
					AttachmentDTO dtos = new AttachmentDTO();
					dtos.setAttachmentName(attrArrs[0]);
					dtos.setType(type);
					
					//配置项新增附件时判断重复 will
					PageDTO pageDto = attachmentDAO.findattachmentPager(dtos, 0, 100, "createTime", "desc"); 
					List<Attachment> lis = (List<Attachment>) pageDto.getData();
					 
					Attachment attr = new Attachment();
					//boolean add = true;
					if (lis != null && lis.size() > 0 && type.equals(lis.get(0).getType())) {
						attr = lis.get(0);
						//add=false;
					}
					
					attr.setUrl(attrArrs[1]);
					attr.setAttachmentName(attrArrs[0]);
					attr.setSize(Long.valueOf(attrArrs[2]));
					attr.setType(type);
					attr.setCreateTime(new Date());
					try {
						// 文件提取的文本信息
						String attachementContent = extractTextFromAttachment.getTextFromAttcahment(attrArrs[1]);
						if (attachementContent == null) {// 将文件名放入
							attachementContent = attrArrs[0];
						}
						attr.setAttachmentContent(attachementContent);
						attr.setCreator(appctx.getCurrentLoginName());
						attrs.add(attachmentDAO.merge(attr));
					} catch (Exception ex) {
						LOGGER.error("保存附件并返回LIST", ex);
					}
				}

			}
		}
		return attrs;
	}

	/**
	 * 获取图片流
	 */
	public InputStream getImageStream(Long aid) {
		if (aid != null) {
			InputStream imageStream = null;
			Attachment att = attachmentDAO.findById(aid);
			String fileUrl = att.getUrl();
			String filePath = AppConfigUtils.getInstance().getAttachmentPath() + File.separator + fileUrl;
			File file = new File(filePath);
			try {
				imageStream = new FileInputStream(file);
			} catch (Exception e) {
				throw new ApplicationException("ERROR_ATTACHMENT_FAIL_READ\n", e);
			}
			return imageStream;
		} else {
			throw new ApplicationException("ERROR_AID_NULL", "ERROR_AID_IS_NULL");
		}

	}

	/**
	 * 根据文件后缀获取ContentType
	 * 
	 * @param fileExt
	 */
	public String switchContentType(String fileExt) {
		String result="";
		Map<String, String> typeMaps = new HashMap<String, String>();

		typeMaps.put("gif", "image/GIF");
		typeMaps.put("png", "image/PNG");
		typeMaps.put("jpg", "image/JPEG");
		typeMaps.put("bmp", "image/BMP");
		typeMaps.put("txt", "text/plain");
		typeMaps.put("doc", "application/msword");
		typeMaps.put("xls", "application/vnd.ms-excel");
		typeMaps.put("ppt", "application/mspowerpoint");
		typeMaps.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
		typeMaps.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
		typeMaps.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
		if (typeMaps.get(fileExt) == null) 
			result= "application/" + fileExt;
		else
			result= typeMaps.get(fileExt);
		return result;
	}
	
	/**
	 * 文件写入
	 * @param fileUrl
	 */
	private File printWriterFile(String fileUrl){
		String fileName = ATTACHMENTPATH;
		if(StringUtils.hasText(fileName)){
			fileName = fileName.replace("\\", "/")+File.separator+ fileUrl;
		}else {
			fileName = fileUrl;
		}
		File file = new File(fileName);
		if (!file.exists()) {
			HttpServletResponse response = ServletActionContext.getResponse();
			LanguageContent lc = LanguageContent.getInstance();
			response.setContentType("text/html;charset=UTF-8");
			response.setCharacterEncoding("UTF-8");// 防止弹出的信息出现乱码
			PrintWriter out = null;
			try {
				out = response.getWriter();
				out.print("<script>alert('" + lc.getContent("error.500").replaceAll("<br/>", " ") + "')</script>");
			} catch (IOException e) {
				LOGGER.error("Attachment download", e);
			} finally {
				if (out != null) {
					out.flush();
					out.close();
				}
			}
		}
		return file;
	}

	/**
	 * 附件下载
	 * @param attachment
	 * @return AttachmentDownloadDTO
	 */
	public AttachmentDownloadDTO downloadAttachment(Attachment attachment) {
		AttachmentDownloadDTO addto = new AttachmentDownloadDTO();
		String fileUrl = attachment.getUrl();
		File file = printWriterFile(fileUrl);
		try {
			addto.setDownloadStream(new FileInputStream(file));
			addto.setDownloadFileName(new String(attachment.getAttachmentName().getBytes("GB2312"), "ISO-8859-1"));
		} catch (FileNotFoundException e) {
			throw new ApplicationException("ERROR_ATTACHMENT_FAIL_READ\n", e);
		} catch (UnsupportedEncodingException e) {
			throw new ApplicationException(e);
		}
		String fileExt = fileUrl.substring(fileUrl.lastIndexOf(".") + 1, fileUrl.length()).toLowerCase();
		addto.setDownloadContentType(switchContentType(fileExt));
		return addto;
	}
	/**
	 * 删除附件
	 * @param downloadAttachmentId
	 */
	public void deleteAttachment(Long downloadAttachmentId){
		Attachment attachment = findAttachmentById(downloadAttachmentId);
    	String fileName = ATTACHMENTPATH.replace("\\", "/")+"/"+  attachment.getUrl();
		/*if(StringUtils.hasText(fileName)){
			fileName = ATTACHMENTPATH+"/"+ attachment.getUrl();
		}else{
			fileName = attachment.getUrl();
		}*/
    	File file = new File(fileName);
    	if(file.exists()){
    		file.delete();
    	}
	}
	/**
	 * 判断文件是否存在
	 * @param imagePath
	 * @return boolean
	 */
	public boolean isFileExit(String imagePath){
		boolean result = false ;
		String fileName = ATTACHMENTPATH.replace("\\", "/")+"/"+ imagePath;
		/*if(StringUtils.hasText(fileName)){
			fileName = ATTACHMENTPATH.replace("\\", "/")+"/"+ imagePath;
		}else{
			fileName = imagePath;
		}*/
    	File file=new File(fileName);
    	if(file.exists()){//判断文件的存在性
    		result=true;
		}
    	return result;
	}
	
	/**
	 * 对比列表，移除重复的.
	 * 
	 * @param attachments
	 * @param newAttachments
	 */
	public List<Attachment> removeDuplicateAttachment(List<Attachment> attachments, List<Attachment> newAttachments) {
		List<Attachment> list = null;
		if (attachments != null && attachments.size() > 0) {
			if (newAttachments != null && newAttachments.size() > 0) {
				for (Attachment attr : attachments) {
					for (int i = newAttachments.size() - 1; i >= 0; i--) {
						if (attr.getAttachmentName().equals(newAttachments.get(i).getAttachmentName())) {
							newAttachments.remove(newAttachments.get(i));
						}
					}
				}
				attachments.addAll(newAttachments);
			} 
			list = attachments;
		} else {
			if (newAttachments != null && newAttachments.size() > 0) {
				list = newAttachments;
			}
		}
		return list;
	}
	/**
	 * 文件读入
	 * @param fileUrl
	 */
	public File readFileByUrl(String fileUrl){
		File file = null;
		String fileName = ATTACHMENTPATH;
		if(StringUtils.hasText(fileName)){
			fileName = fileName.replace("\\", "/")+File.separator+ fileUrl;
		}else {
			fileName = fileUrl;
		}
		try {
			file = new File(fileName);
		} catch (Exception e) {
			LOGGER.error("FILE_READ_ERROR", e);
		}
		return file;
	}
}
